package com.youmeek.ssm.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

public class ApplicationBeanUtil {

    private static ApplicationBeanUtil instance;

    @Autowired
    private BeanHunter beanHunter;

    @PostConstruct
    public void afterConstruct() {
        instance = this;
        instance.beanHunter = this.beanHunter;
    }

    public <T> T getBeanByName(String name, Class<T> c) {
        return beanHunter.getBeanByName(name, c);
    }

    public Object getBeanByName(String name) {
        return beanHunter.getBeanByName(name);
    }

    public <T> T getBeanByClass(Class<T> c) {
        return beanHunter.getBeanByClass(c);
    }

    /**
     * 通过bean的名称和类型获取注册在applicationContext中的实例
     *
     * @param name bean的名字
     * @param c    bean的类型
     * @return
     */
    public static <T> T findBeanByName(String name, Class<T> c) {
        return instance.getBeanByName(name, c);
    }

    /**
     * 通过bean的名称获取注册在applicationContext中的实例
     *
     * @param name bean的名字
     * @return
     */
    public static Object findBeanByName(String name) {
        return instance.getBeanByName(name);
    }

    /**
     * 通过bean的类型获取注册在applicationContext中的实例
     *
     * @param name bean的名字
     * @param c    bean的类型
     * @return
     */
    public static <T> T findBeanByClass(Class<T> c) {
        return instance.getBeanByClass(c);
    }

    @Component
    private static class BeanHunter implements ApplicationContextAware {

        private ApplicationContext applicationContext;

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }

        public <T> T getBeanByName(String name, Class<T> c) {
            return applicationContext.getBean(name, c);
        }

        public <T> T getBeanByClass(Class<T> c) {
            return applicationContext.getBean(c);
        }

        public Object getBeanByName(String name) {
            return applicationContext.getBean(name);
        }

    }
}
